/**
 * 布尔值,最基本的数据类型就是简单的true/false值，在JavaScript和TypeScript里叫做boolean（其它语言中也一样）。
*/
let isDone : boolean = true

/**数字
 * 和JavaScript一样，TypeScript里的所有数字都是浮点数。 这些浮点数的类型是 number。 除了支持十进制和十六进制字面量，TypeScript还支持ECMAScript 2015中引入的二进制和八进制字面量。
 */

let xiaomingAge: number = 14;
let xiaoliAge: number = 15;
let xiaoweiAge: number = 16;



/**字符串
JavaScript程序的另一项基本操作是处理网页或服务器端的文本数据。 像其它语言里一样，我们使用 string表示文本数据类型。 和JavaScript一样，可以使用双引号（ "）或单引号（'）表示字符串。 */
let zhaoName :string = "hello";
let sentence: string = "Hello, my name is " + zhaoName + ".\n\n" +
    "I'll be " + (xiaoliAge + 1) + " years old next month.";

/**数组
TypeScript像JavaScript一样可以操作数组元素。 有两种方式可以定义数组。 第一种，可以在元素类型后面接上 []，表示由此类型元素组成的一个数组：
第二种方式是使用数组泛型，Array<元素类型>：
*/
let list : number[] = [1,2,3];
let nameList : Array<number> = [1,2,3];

/**元组 Tuple
元组类型允许表示一个已知元素数量和类型的数组，各元素的类型不必相同。 比如，你可以定义一对值分别为 string和number类型的元组。
在TypeScript中使用元组，其实和数组的定义差不多，但和数组不同的是元组的数量是固定的，元组的好处在于可以把多个元素作为一个单元传递

*/
let x :[string,number];
x = ['hello',10]
console.log(x[0].substr(1));
//console.log(x[1].substr(1)); // Error, 'number' does not have 'substr'
let y :[string,number,number];
y = ['jane',10,20]

/**枚举
enum类型是对JavaScript标准数据类型的一个补充。 像C#等其它语言一样，使用枚举类型可以为一组数值赋予友好的名字。
 */
enum Color{Red,Green,Blue}
let c: Color = Color.Green;

/**默认情况下，从0开始为元素编号。 你也可以手动的指定成员的数值
 * 
 */
enum Color2{Red=2,Green=2,Blue=4}
let colorName:string = Color[2]
console.log(colorName)


/**Any
有时候，我们会想要为那些在编程阶段还不清楚类型的变量指定一个类型。 这些值可能来自于动态的内容，比如来自用户输入或第三方代码库。 这种情况下，我们不希望类型检查器对这些值进行检查而是直接让它们通过编译阶段的检查。 那么我们可以使用 any类型来标记这些变量
 */
let notSure: any = 4;
notSure = "maybe a string";
notSure = false;


/**当你只知道一部分数据的类型时，any类型也是有用的。 比如，你有一个数组，它包含了不同的类型的数据： */
let anyList1 : any[] = [1,true,"free"];

/**某种程度上来说，void类型像是与any类型相反，它表示没有任何类型。 当一个函数没有返回值时，你通常会见到其返回值类型是 void： */
function warnUser(): void {
  console.log("this is my warning message");
}
/**声明一个void类型的变量没有什么大用，因为你只能为它赋予undefined和null：*/ 
let unusable: void = undefined;



/**Never
never类型表示的是那些永不存在的值的类型。 例如， never类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型； 变量也可能是 never类型，当它们被永不为真的类型保护所约束时。 
never类型是任何类型的子类型，也可以赋值给任何类型；然而，没有类型是never的子类型或可以赋值给never类型（除了never本身之外）。 即使 any也不可以赋值给never。
*/
// 返回never的函数必须存在无法达到的终点
function error(message: string):never{
  throw new Error(message);
}

// 推断的返回值类型为never
function fail(){
  return error("something failed");
}

// 返回never的函数必须存在无法达到的终点
function infiniteLoop():never{
  while(true){

  }
}


/**Object
object表示非原始类型，也就是除number，string，boolean，symbol，null或undefined之外的类型。
使用object类型，就可以更好的表示像Object.create这样的API。例如： */
declare function create(o:object| null):void;
create({prop:0});
create(null);
// create(42); //Error
// create("string");
// create(false);
// create(undefined);



/**类型断言
有时候你会遇到这样的情况，你会比TypeScript更了解某个值的详细信息。 通常这会发生在你清楚地知道一个实体具有比它现有类型更确切的类型。
通过类型断言这种方式可以告诉编译器，“相信我，我知道自己在干什么”。 类型断言好比其它语言里的类型转换，但是不进行特殊的数据检查和解构。 它没有运行时的影响，只是在编译阶段起作用。 TypeScript会假设你，程序员，已经进行了必须的检查。
类型断言有两种形式。 其一是“尖括号”语法： */
let someValue : any = "this is a string";
let strLength: number = (<string> someValue).length;

/**另一个为as语法*/
strLength = (someValue as string).length;


/**关于let
你可能已经注意到了，我们使用let关键字来代替大家所熟悉的JavaScript关键字var。 let关键字是JavaScript的一个新概念，TypeScript实现了它。 我们会在以后详细介绍它，很多常见的问题都可以通过使用 let来解决，所以尽可能地使用let来代替var吧。 */